// @Author EthanScriptOn
// @Desc
package util

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
)

// FileExist The file exists
func FileExist(filePath string) (bool, error) {
	if filePath == "" {
		return false, fmt.Errorf("file path is empty: [%+v]", filePath)
	}
	stat, err := os.Stat(filePath)
	if err == nil {
		return !stat.IsDir(), nil
	}
	if os.IsNotExist(err) {
		return false, fmt.Errorf("not found file path: [%+v]", filePath)
	}
	return false, err
}

// IsDir Whether it is a directory or not
func IsDir(path string) (bool, error) {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false, err
	}
	return fileInfo.IsDir(), nil
}

// GetDirectory Get the catalog
func GetDirectory(filePath string) string {
	dir := filepath.Dir(filePath)
	return dir
}

// GetFileExtension Get the file extension
func GetFileExtension(filePath string) string {
	baseName := filepath.Base(filePath)
	if dotIndex := len(baseName) - len(filepath.Ext(baseName)); dotIndex > 0 {
		return baseName[dotIndex:]
	}
	return ""
}

// GetDirFiles Get all the files in the directory
func GetDirFiles(filePath string, dirFilesPath *[]string) (*[]string, error) {
	if filePath == "" {
		return dirFilesPath, fmt.Errorf("file path is empty: [%+v]", filePath)
	}
	dirFiles, err := os.ReadDir(filePath)
	if err != nil {
		return dirFilesPath, err
	}
	for _, dirFilePath := range dirFiles {
		dirChildPath := filePath + "/" + dirFilePath.Name()
		if dirFilePath.IsDir() {
			files, err := GetDirFiles(dirChildPath, dirFilesPath)
			if err != nil {
				return dirFilesPath, err
			}
			*dirFilesPath = append(*dirFilesPath, *files...)
		} else {
			*dirFilesPath = append(*dirFilesPath, dirChildPath)
		}
	}
	return dirFilesPath, nil
}

// FileLoad Parse the file
func FileLoad(filePath string) ([]string, error) {
	file, err := os.Open(filePath)
	lines := make([]string, 0)
	if err != nil {
		return lines, err
	}
	reader := bufio.NewReader(file)
	for {
		getBytes, err := reader.ReadBytes('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			return lines, err
		}
		lines = append(lines, string(getBytes))
	}
	return lines, nil
}

// FileInformation File Information
type FileInformation struct {
	FilePath   string
	AbsPath    string
	FileName   string
	FileType   string
	CurrentDir string
}

// IsValid Whether the file information is valid
func (f *FileInformation) IsValid() error {
	if f.FilePath == "" {
		return errors.New("file path is empty! ")
	}
	if f.AbsPath == "" {
		return errors.New("abs path is empty! ")
	}
	if f.FileName == "" {
		return errors.New("file name is empty! ")
	}
	if f.FileType == "" {
		return errors.New("file type is empty! ")
	}
	if f.CurrentDir == "" {
		return errors.New("current dir is empty! ")
	}
	return nil
}

// GenerateFileInformation Generate file information
func GenerateFileInformation(filePathVal string) (*FileInformation, error) {
	exist, err := FileExist(filePathVal)
	if !exist {
		return nil, fmt.Errorf("filePath: [%+v] can not found ", filePathVal)
	}
	if err != nil {
		return nil, err
	}
	absPath, err := filepath.Abs(filePathVal)
	if err != nil {
		return nil, err
	}
	fileName := filepath.Base(filePathVal)
	fileType := filepath.Ext(filePathVal)
	dir := filepath.Dir(filePathVal)
	return &FileInformation{
		FilePath:   filePathVal,
		AbsPath:    absPath,
		FileName:   fileName,
		FileType:   fileType,
		CurrentDir: dir,
	}, nil
}
